package com.macro.mall.tiny.modules.oms.controller;


import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.macro.mall.tiny.common.api.CommonResult;
import com.macro.mall.tiny.common.api.ResultCode;
import com.macro.mall.tiny.modules.oms.model.OmsOrder;
import com.macro.mall.tiny.modules.oms.model.OmsPromoCode;
import com.macro.mall.tiny.modules.oms.model.OmsPromoCodeApply;
import com.macro.mall.tiny.modules.oms.model.dto.BatchUpdatePromoCodeDTO;
import com.macro.mall.tiny.modules.oms.service.OmsOrderService;
import com.macro.mall.tiny.modules.oms.service.OmsPromoCodeApplyService;
import com.macro.mall.tiny.modules.oms.service.OmsPromoCodeService;
import com.macro.mall.tiny.modules.ums.model.UmsAdmin;
import com.macro.mall.tiny.modules.ums.model.UmsMember;
import com.macro.mall.tiny.modules.ums.service.UmsAdminService;
import com.macro.mall.tiny.security.component.JwtAuthenticationTokenFilter;
import com.macro.mall.tiny.security.util.JwtTokenUtil;
import com.macro.mall.tiny.security.util.MemberContext;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import net.bytebuddy.utility.RandomString;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.macro.mall.tiny.modules.oms.controller.OmsOrderController.getGoodMap;

/**
 * <p>
 * 会员优惠码表 前端控制器
 * </p>
 *
 * @author tyrone
 * @since 2024-10-23
 */
@RestController
@RequestMapping("/oms/omsPromoCode")
@Api(tags = "OmsPromoCodeController")
@Tag(name = "OmsPromoCodeController", description = "优惠码管理")
public class OmsPromoCodeController {

    @Autowired
    private OmsPromoCodeService omsPromoCodeService;

    @Autowired
    private OmsPromoCodeApplyService omsPromoCodeApplyService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UmsAdminService umsAdminService;

    @Autowired
    private OmsOrderService omsOrderService;


    @ApiOperation("前台申请会员优惠码")
    @GetMapping("apply")
    public CommonResult<Void> applyPromoCode() {
        String openId = MemberContext.getMember().getOpenId();
        if (omsPromoCodeApplyService.query().eq("open_id", openId).eq("assess_status", 0).count() > 0) {
            return CommonResult.failed("存在未审核优惠码请耐心等待管理员审核");
        }
        if (omsPromoCodeService.query().eq("open_id", openId).eq("status", 1).count() > 0) {
            return CommonResult.failed("已存在优惠码");
        }
        OmsPromoCodeApply omsPromoCodeApply = new OmsPromoCodeApply();
        omsPromoCodeApply.setOpenId(openId);
        omsPromoCodeApply.setCreateTime(new Date());
        omsPromoCodeApplyService.save(omsPromoCodeApply);
        return CommonResult.success(null);
    }

    @ApiOperation("前台获取当前会员的优惠码")
    @GetMapping("get")
    public CommonResult<List<OmsPromoCode>> getPromoCode() {
        String openId = MemberContext.getMember().getOpenId();
        List<OmsPromoCode> list = omsPromoCodeService.query()
                .eq("open_id", openId).eq("status", 1).list();
        if (list == null || list.isEmpty()) {
            return CommonResult.success(null, "该用户无优惠码");
        }
        return CommonResult.success(list);
    }

    @ApiOperation("前台校验会员的优惠码")
    @GetMapping("getOmsPromoCode")
    public CommonResult<OmsPromoCode> getPromoCode(@RequestParam String promoCode) {
        UmsMember member = MemberContext.getMember();
        if (member == null) {
            return CommonResult.failed("请先登录");
        }
        String openId = member.getOpenId();
        OmsPromoCode code = omsPromoCodeService.query()
                .eq("promo_code", promoCode).eq("status", 1).one();
        if (code == null || code.getOpenId().equals(openId)) {
            return CommonResult.failed("不存在改优惠券或无效");
        }
        return CommonResult.success(code);
    }

    @ApiOperation("后台审核用户优惠码申请")
    @GetMapping("audit")
    public CommonResult<Void> auditPromoCodeApply(@ApiParam("申请id") @RequestParam Integer id,
                                                  @ApiParam("审核状态") @RequestParam Integer status,
                                                  @ApiParam("优惠码") @RequestParam String promoCode,
                                                  @ApiParam("返点 单位% ") @RequestParam(required = false) Double rebate,
                                                  @ApiParam("authorization") @RequestHeader("authorization") String authorization) {
        String adminUsername = jwtTokenUtil.getUserNameFromToken(authorization.replace("Bearer ", ""));
        UmsAdmin admin = umsAdminService.getAdminByUsername(adminUsername);
        OmsPromoCodeApply omsPromoCodeApply = omsPromoCodeApplyService.getById(id);

        if (omsPromoCodeApply == null) {
            return CommonResult.failed("申请不存在");
        }
        if (omsPromoCodeApply.getAssessStatus() != 0) {
            return CommonResult.failed("申请已审核");
        }
        Date current = new Date();

        omsPromoCodeApply.setAssessStatus(status);
        omsPromoCodeApply.setAssessTime(current);
        omsPromoCodeApply.setAssessAdminId(admin.getId());
        if (status == 1) {
//            String promoCode = buildPromoCode();
            omsPromoCodeApply.setPromoCode(promoCode);

            OmsPromoCode omsPromoCode = new OmsPromoCode();
            omsPromoCode.setOpenId(omsPromoCodeApply.getOpenId());
            omsPromoCode.setPromoCode(promoCode);
            omsPromoCode.setCreateTime(current);
            omsPromoCode.setStatus(1);
            omsPromoCode.setPromoRebates(rebate);
            omsPromoCode.setApplyTime(omsPromoCodeApply.getCreateTime());
            omsPromoCodeService.save(omsPromoCode);
        }
        omsPromoCodeApplyService.updateById(omsPromoCodeApply);
        return CommonResult.success(null);
    }

    @ApiOperation("万能分页后台获取用户优惠码申请列表")
    @PostMapping("page")
    public CommonResult<IPage<OmsPromoCodeApply>> page(@RequestBody OmsPromoCodeApply omsPromoCodeApply) {
        QueryWrapper<OmsPromoCodeApply> query = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(omsPromoCodeApply.getOpenId())) query.eq("open_id", omsPromoCodeApply.getOpenId());
        if (omsPromoCodeApply.getAssessStatus() != null) query.eq("assess_status", omsPromoCodeApply.getAssessStatus());
        if (omsPromoCodeApply.getAssessAdminId() != null)
            query.eq("assess_admin_id", omsPromoCodeApply.getAssessAdminId());

        if (omsPromoCodeApply.getCreateTimeStart() != null)
            query.gt("create_time", omsPromoCodeApply.getCreateTimeStart());
        if (omsPromoCodeApply.getCreateTimeEnd() != null) query.lt("create_time", omsPromoCodeApply.getCreateTimeEnd());
        if (omsPromoCodeApply.getAssessTimeStart() != null)
            query.gt("assess_time", omsPromoCodeApply.getAssessTimeStart());
        if (omsPromoCodeApply.getAssessTimeEnd() != null) query.lt("assess_time", omsPromoCodeApply.getAssessTimeEnd());
        query.orderByDesc("create_time");
        Page<OmsPromoCodeApply> page = omsPromoCodeApplyService.page(new Page<>(omsPromoCodeApply.getPageNum(), omsPromoCodeApply.getPageSize(), Boolean.TRUE), query);
        Map<Long, String> map = umsAdminService.list().stream().collect(Collectors.toMap(UmsAdmin::getId, UmsAdmin::getUsername));
        for (OmsPromoCodeApply record : page.getRecords()) {
            record.setAssessAdminUsername(map.getOrDefault(record.getAssessAdminId(), "admin"));
        }
        return CommonResult.success(page);

    }

    @ApiOperation("万能分页后台获取用户优惠码列表 支持openId status createTimeStart createTimeEnd applyTimeStart applyTimeEnd ")
    @PostMapping("pagePromoCode")
    public CommonResult<IPage<OmsPromoCode>> commonResult(@RequestBody OmsPromoCode omsPromoCode) {
        QueryWrapper<OmsPromoCode> query = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(omsPromoCode.getOpenId())) query.eq("open_id", omsPromoCode.getOpenId());

        if (omsPromoCode.getStatus() != null) query.eq("status", omsPromoCode.getStatus());

        if (omsPromoCode.getPromoRebates() != null) query.eq("promo_rebates", omsPromoCode.getPromoRebates());

        if (omsPromoCode.getCreateTimeStart() != null)
            query.gt("create_time", omsPromoCode.getCreateTimeStart());
        if (omsPromoCode.getCreateTimeEnd() != null)
            query.lt("create_time", omsPromoCode.getCreateTimeEnd());

        if (omsPromoCode.getApplyTimeStart() != null)
            query.gt("apply_time", omsPromoCode.getApplyTimeStart());
        if (omsPromoCode.getApplyTimeEnd() != null)
            query.lt("apply_time", omsPromoCode.getApplyTimeEnd());

        if (omsPromoCode.getPromoRebatesStart() != null) {
            query.gt("promo_rebates", omsPromoCode.getPromoRebatesStart());
        }
        if (omsPromoCode.getPromoRebatesEnd() != null) {
            query.lt("promo_rebates", omsPromoCode.getPromoRebatesEnd());
        }

        query.orderByDesc("create_time");
        Page<OmsPromoCode> page = omsPromoCodeService.page(new Page<>(omsPromoCode.getPage(), omsPromoCode.getSize(), Boolean.TRUE), query);
        return CommonResult.success(page);
    }

    @ApiOperation("批量更新用户优惠码返点")
    @PostMapping("batchUpdatePromoCode")
    public CommonResult<Void> batchUpdatePromoCode(@RequestBody @Validated BatchUpdatePromoCodeDTO dto) {
        List<OmsPromoCode> omsPromoCodes = new ArrayList<>();
        if (dto.getPromoRebates() == null && dto.getStatus() == null) {
            return CommonResult.failed(ResultCode.VALIDATE_FAILED);
        }
        for (Integer id : dto.getIds()) {
            OmsPromoCode omsPromoCode = new OmsPromoCode();
            omsPromoCode.setId(id);
            omsPromoCode.setPromoRebates(dto.getPromoRebates());
            omsPromoCode.setStatus(dto.getStatus());
            omsPromoCodes.add(omsPromoCode);
        }
        omsPromoCodeService.updateBatchById(omsPromoCodes);
        return CommonResult.success(null);
    }



    @ApiOperation("批量审核用户优惠码申请")
    @PostMapping("batchAudit")
    public CommonResult<Void> batchAuditPromoCodeApply(@RequestBody @Validated BatchAuditPromoCodeApplyDTO dto,
                                                       @ApiParam("authorization") @RequestHeader("authorization") String authorization) {

        String adminUsername = jwtTokenUtil.getUserNameFromToken(authorization.replace("Bearer ", ""));
        UmsAdmin admin = umsAdminService.getAdminByUsername(adminUsername);
        List<OmsPromoCodeApply> omsPromoCodeApplies = new ArrayList<>();
        Date current = new Date();
        List<OmsPromoCode> omsPromoCodes = new ArrayList<>();
        List<OmsPromoCodeApply> applies = omsPromoCodeApplyService.listByIds(dto.getIds());
        for (OmsPromoCodeApply apply : applies) {
            OmsPromoCodeApply omsPromoCodeApply = new OmsPromoCodeApply();
            omsPromoCodeApply.setId(apply.getId());
            omsPromoCodeApply.setAssessStatus(dto.getStatus());
            omsPromoCodeApply.setAssessTime(current);
            omsPromoCodeApply.setAssessAdminId(admin.getId());

            omsPromoCodeApplies.add(omsPromoCodeApply);
            if (dto.getStatus() == 1) {
                String promoCode = buildPromoCode();
                omsPromoCodeApply.setPromoCode(promoCode);

                OmsPromoCode omsPromoCode = new OmsPromoCode();
                omsPromoCode.setOpenId(apply.getOpenId());
                omsPromoCode.setPromoCode(promoCode);
                omsPromoCode.setCreateTime(current);
                omsPromoCode.setStatus(1);
                omsPromoCode.setPromoRebates(omsPromoCode.getPromoRebates());
                omsPromoCode.setApplyTime(apply.getCreateTime());
                omsPromoCodes.add(omsPromoCode);
            }
        }

        omsPromoCodeApplyService.updateBatchById(omsPromoCodeApplies);
        omsPromoCodeService.saveBatch(omsPromoCodes);
        return CommonResult.success(null);
    }

    @Data
    static class BatchAuditPromoCodeApplyDTO {
        @ApiModelProperty("申请id列表")
        @NotNull
        private List<Integer> ids;

        @ApiModelProperty("审核状态")
        @NotNull
        private Integer status;
        @ApiModelProperty("返点 单位% ")
        private Double rebate;
    }


    @ApiOperation("查看会员优惠码使用详情")
    @GetMapping("detail")
    public CommonResult<List<OmsPromoOrderVO>> detail(@ApiParam("优惠码id") @RequestParam Integer promoCodeId) {
        UmsMember member = MemberContext.getMember();
        OmsPromoCode omsPromoCode = omsPromoCodeService.query().eq("id", promoCodeId).eq("open_id", member.getOpenId()).one();
        if (omsPromoCode == null) {
            return CommonResult.failed("优惠码不存在");
        }
        String promoCode = omsPromoCode.getPromoCode();

        List<OmsOrder> orderList = omsOrderService.query().eq("promo_code", promoCode).eq("status", 1).orderByDesc("pay_time").list();
        List<OmsPromoOrderVO> vos = new ArrayList<>();
        for (OmsOrder omsOrder : orderList) {
            OmsPromoOrderVO vo = new OmsPromoOrderVO();
            vo.setOrderNo(omsOrder.getOrderId());
            vo.setPayTime(omsOrder.getPayTime());
            vo.setGoodName(getGoodMap().get(omsOrder.getGoodId()).getName());
            //todo 利润计算
            vo.setMargins(omsOrder.getTotalFee() - omsOrder.getActualFee());
            vos.add(vo);
        }
        return CommonResult.success(vos);
    }


    private String buildPromoCode() {
        String promoCode = RandomUtil.randomString(6);
        while (omsPromoCodeService.query().eq("promo_code", promoCode).count() > 0) {
            promoCode = RandomUtil.randomString(6);
        }
        return promoCode;
    }

    @Data
    public class OmsPromoOrderVO {
        @ApiModelProperty("用户昵称")
        private String nickName;
        @ApiModelProperty("订单号")
        private String orderNo;
        @ApiModelProperty("支付时间")
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private Date payTime;
        @ApiModelProperty("商品名称")
        private String goodName;
        @ApiModelProperty("利润")
        private Integer margins;
    }

    public class OmsApplySettleDTO {
        @ApiModelProperty("用户openId")
        private String openId;

        @ApiModelProperty("提现金额")
        private Integer fee;
    }


}

